home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
libraris
/
gimme.6
< prev
next >
Wrap
Text File
|
1988-12-02
|
58KB
|
2,453 lines
Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i079: gimme.lib - misc library routines, Part06/07
Message-ID: <10417@swan.ulowell.edu>
Date: 2 Dec 88 01:03:44 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2442
Approved: page@swan.ulowell.edu
Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
Posting-number: Volume 2, Issue 79
Archive-name: libraries/gimme.6
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# picture.c
# postext.c
# requester.c
# screen.c
# scrollbar.c
# sound.c
# stdstuff.c
# subtask.c
# subtinit.c
# timer.c
# timerstuff.c
# window.c
# This archive created: Thu Dec 1 19:52:33 1988
cat << \SHAR_EOF > picture.c
/*
* FILE: picture.c
* Support routines for reading IFF/ILBM files.
*
* Public Domain, but keep our names in it as the original authors.
* 08-Dec-87 Rico Mariani original code (modified by JST)
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#define I_AM_PICTURE
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/picture.h"
#include "gimmelib/postext.h"
#include "gimmelib/minterm.h"
#include <stdio.h>
#define GET(iffile) getc( iffile )
#define getId getLong
#define getLen getLong
#define getByte GET
#define skip(len, file) fseek(file, (long)(len), 1)
#define getBMH(bmh, file) fread(bmh, sizeof(BitMapHeader), 1, file)
/* requires an existent variable 'char *errmsg' and a label 'failure_return' */
#define fail_and_return(msg) {errmsg = msg; goto failure_return;}
/* forward declarations */
static LONG getLong();
static WORD getWord();
static ULONG makeBM();
static char noMemMsg[] = "insufficient memory\n";
static char badFileMsg[] = "corrupt or incomplete file\n";
PICTURE *gimmePicture( filename, myflags )
UBYTE *filename;
ULONG myflags;
{
LONG len, id;
PICTURE *pic = NULL;
BYTE *p;
void *mh = NULL;
FILE *file = NULL;
char *errmsg = " ";
SHORT i;
if( !(file = fopen(filename, "r")) ) {
fail_and_return( "unable to open iff picture file for read\n" );
}
if( getId(file) != ID_FORM ) {
fail_and_return( "not IFF format\n" );
}
getLen( file );
if( getId(file) != ID_ILBM ) {
fail_and_return( "not ILBM format\n" );
}
for( ;; ) {
getChunk( &id, &len, file );
if( ferror(file) || feof(file) ) {
fail_and_return( badFileMsg );
}
switch( id ) {
case ID_BMHD:
pic = chainAllocMem( &mh, (ULONG)sizeof(PICTURE),
MEMF_PUBLIC | MEMF_CLEAR );
if( !pic ) {
fail_and_return( noMemMsg );
}
getBMH( &pic->bmh, file );
if( len & 1 ) {
GET(file);
}
break;
case ID_CMAP:
if( getLut(pic, len, file) ) {
fail_and_return( "unable to get color table\n" );
}
break;
case ID_BODY:
if( !pic ) {
fail_and_return( "didn't find BMHD chunk\n" );
return( NULL );
}
switch( pic->bmh.masking ) {
case mskNone:
case mskLasso:
case mskHasTranCol:
break;
default:
printf("Error, unsupported masking type\n");
return( NULL );
} /* switch */
pic->xsize = pic->bmh.w;
if( (pic->myflags = makeBM(pic, myflags)) == GBP_ERROR ) {
return( NULL );
}
switch( pic->bmh.compression ) {
case cmpNone:
if( getBody(pic->bm, pic->myflags, file) ) {
fail_and_return( "error in uncompressed body\n" );
}
break;
case cmpByteRun1:
if( getCmpBody(pic->bm, file) ) {
fail_and_return( "error in compressed body\n" );
}
break;
default:
fail_and_return( "unknown compression form\n" );
return( NULL );
} /* switch */
if( ferror(file) ) {
fail_and_return( badFileMsg );
}
pic->memhead = mh;
fclose( file );
return( pic );
break;
case ID_DEST:
case ID_SPRT:
case ID_CAMG:
case ID_CRNG:
case ID_CCRT:
default: /* unimplemented chunk type */
skip( EVEN(len), file );
break;
} /* switch */
} /* for */
failure_return: {}
if( Output() ) {
Write( Output(), errmsg, (ULONG)strlen(errmsg) );
}
if( mh ) {
chainFreeMem( mh );
}
if( file ) {
fclose( file );
}
return( NULL );
} /* gimmePicture */
static ULONG makeBM( pic, myflags )
register PICTURE *pic;
ULONG myflags;
{
UBYTE *plane;
if( !(pic->bm = AllocMem((ULONG)sizeof(struct BitMap), MEMF_PUBLIC)) ) {
return( GBP_ERROR );
}
InitBitMap( pic->bm, (long) pic->bmh.nPlanes, (long) pic->bmh.w,
(long) pic->bmh.h );
return( gimmeBitPlanes(pic->bm, myflags) );
} /* makeBM */
short getRidOfPicture( picture )
PICTURE *picture;
{
#ifdef GIMME_WIMPY
if( picture ) {
return( -1 );
}
#endif
if( picture->colormap.ColorTable ) {
FreeMem( picture->colormap.ColorTable,
(ULONG) picture->colormap.Count * sizeof(USHORT) );
}
if( picture->bm ) {
getRidOfBitPlanes( picture->bm, picture->myflags );
FreeMem( picture->bm, (ULONG)sizeof(struct BitMap) );
}
chainFreeMem( picture->memhead );
return( 0 );
} /* getRidOfPicture */
short positionPicture( rp, myflags, pic, minterm, x, y )
struct RastPort *rp;
ULONG myflags;
PICTURE *pic;
SHORT minterm;
register SHORT x, y;
{
SHORT left, top;
SHORT width, height;
SHORT temp;
struct BitMap *bm;
#ifdef GIMME_WIMPY
if( !pic || !rp ) {
return( -1 );
}
#endif
left = top = 0;
width = pic->bmh.w;
height = pic->bmh.h;
bm = rp->BitMap;
switch( myflags & GPT_XFLAGS ) {
case GPT_XCENTRE:
x -= width >> 1;
break;
case GPT_XRIGHT:
x -= width;
break;
case GPT_XLEFT:
default:
break;
} /* switch */
switch( myflags & GPT_YFLAGS ) {
case GPT_YBOTTOM:
case GPT_YBASELINE:
y -= height;
break;
case GPT_YCENTRE:
case GPT_YCENTREBASE:
y -= height >> 1;
break;
case GPT_YTOP:
default:
break;
} /* switch */
if( minterm != GIM_MINTERM_DEST ) {
if( x < 0 ) {
width += x;
left -= x;
x = 0;
} else if( (temp = x + width - (bm->BytesPerRow << 3)) > 0 ) {
width -= temp;
}
if( y < 0 ) {
height += y;
top -= y;
y = 0;
} else if( (temp = y + height - bm->Rows) > 0 ) {
height -= temp;
}
if( width > 0 && height > 0 ) {
BltBitMapRastPort( pic->bm, (long) left, (long) top, rp,
(long) x, (long) y,
(long) width, (long) height, (long) minterm );
}
}
return( 0 );
} /* positionPicture */
short usePictureColors( pic, screen )
register PICTURE *pic;
struct Screen *screen;
{
#ifdef GIMME_WIMPY
if( !pic || !screen ) {
return( -1 );
}
#endif
return( setColors(screen, pic->colormap.ColorTable,
(SHORT) pic->colormap.Count) );
} /* usePictureColors */
/* read an IFF Id */
static LONG getLong( file )
FILE *file;
{
register UBYTE p[4];
p[0] = GET(file);
p[1] = GET(file);
p[2] = GET(file);
p[3] = GET(file);
return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
} /* getLong */
/* read an IFF chunk header */
static getChunk( id, len, file )
LONG *id, *len;
FILE *file;
{
*id = getId( file );
*len = getLen( file );
} /* getChunk */
/* get len bytes from the file and put them into memory */
static memget( p, len, file )
UBYTE *p;
LONG len;
FILE *file;
{
for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
fread( p, (int) (len & 0x07fffL), 1, file );
} /* for */
} /* memget */
/* get a word */
static WORD getWord( file )
FILE *file;
{
WORD v;
v = GET(file) << 8;
return( v | GET(file) );
} /* getWord */
static int getCmpBody( bm, file )
struct BitMap *bm;
FILE *file;
{
register short x;
short y, pl;
UBYTE *plane;
UBYTE run_len, verb_len, run_byte;
BYTE v;
register BYTE mybyte;
verb_len = run_len = 0;
/* note: the bit-planes should be clear already */
for( y = 0; y < bm->Rows; ++y ) {
for( pl = 0; pl < bm->Depth; ++pl ) {
plane = bm->Planes[pl] + y * bm->BytesPerRow;
for( x = 0; x < bm->BytesPerRow; ++x ) {
if( run_len ) {
--run_len;
mybyte = run_byte;
} else if( verb_len ) {
--verb_len;
mybyte = GET(file);
} else if( (v = GET(file)) >= 0 ) {
verb_len = v;
mybyte = GET(file);
} else {
run_len = -v;
mybyte = run_byte = GET(file);
}
plane[x] = mybyte;
} /* for */
} /* for */
} /* for */
return( 0 );
} /* getCmpBody */
static int getBody( bm, flags, file )
register struct BitMap *bm;
ULONG flags;
FILE *file;
{
register short i;
if( flags & GBP_CONTIGUOUS ) {
memget( bm->Planes[0], (ULONG)(bm->Depth) * bm->Rows * bm->BytesPerRow,
file );
} else {
for( i = 0; i < bm->Depth; ++i ) {
memget( bm->Planes[i], (ULONG)(bm->Rows) * bm->BytesPerRow, file );
} /* for */
}
return( 0 );
} /* getBody */
static int getLut( pic, len, file )
PICTURE *pic;
LONG len;
FILE *file;
{
SHORT i, ncols;
USHORT red, green, blue;
USHORT *lut;
pic->colormap.Flags = pic->colormap.Type = 0;
ncols = len / 3;
lut = (USHORT *) AllocMem( (ULONG) ncols * sizeof(USHORT), MEMF_PUBLIC );
if( !lut ) {
return( -1 );
}
for( i = 0; i < ncols; ++i ) {
red = GET(file) >> 4;
green = GET(file) >> 4;
blue = GET(file) >> 4;
lut[i] = (red << 8) | (green << 4) | blue;
} /* for */
if( len & 1 ) {
GET(file);
}
pic->colormap.Count = ncols;
pic->colormap.ColorTable = (APTR) lut;
return( 0 );
} /* getLut */
SHAR_EOF
cat << \SHAR_EOF > postext.c
/*
* FILE: postext.c
* Support routines for writing text (or a number) in a rastport,
* with flexible text location specification (eg any corner, centre).
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#define I_AM_POSTEXT
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/postext.h"
SHORT positionText( rp, myflags, s, num, x, y )
register struct RastPort *rp;
register ULONG myflags;
UBYTE *s;
LONG num;
SHORT x, y;
{
register SHORT i, j;
SHORT len, rastlen, maxrastlen;
SHORT maxbit, lowi;
SHORT dest, temp;
SHORT height, baseline;
struct RastPort myrp;
UBYTE buf[12]; /* big enough for max ULONG + '\0' */
#ifdef GIMME_WIMPY
if( !rp ) {
return( -1 );
}
#endif
if( s ) {
len = strlen( s );
} else {
len = sprintf( buf, "%1ld", num );
s = buf;
}
maxrastlen = len * (rp->TxWidth + rp->TxSpacing);
rastlen = TextLength( rp, s, (long) len );
if( myflags & (GPT_YUPWARDS | GPT_YDOWNWARDS) ) {
myrp = *rp; /* copy struct */
myrp.BitMap = gimmeBitMap( rp->BitMap->Depth, rastlen, myrp.TxHeight );
if( !myrp.BitMap ) {
return( -1 );
}
myrp.Layer = NULL; /* make sure no layer else trouble */
myrp.GelsInfo = NULL;
Move( &myrp, 0L, (long) myrp.TxBaseline );
Text( &myrp, s, (long) len );
maxbit = rastlen - 1;
switch( myflags & GPT_XFLAGS ) {
case GPT_XRIGHT:
if( myflags & GPT_YDOWNWARDS ) {
y -= maxbit;
}
break;
case GPT_XCENTRE:
y -= rastlen >> 1;
break;
case GPT_XLEFT:
default:
if( myflags & GPT_YUPWARDS ) {
y -= maxbit;
}
break;
} /* switch */
if( myflags & GPT_XTHICKEN ) { /* if double thickness */
height = (myrp.TxHeight << 1) - 1;
baseline = (myrp.TxBaseline << 1);
} else {
height = myrp.TxHeight - 1;
baseline = myrp.TxBaseline;
}
switch( myflags & GPT_YFLAGS ) { /* make x top of char */
case GPT_YBOTTOM:
if( myflags & GPT_YUPWARDS ) {
x -= height;
}
break;
case GPT_YCENTRE: /* skew to top of char */
if( myflags & GPT_YDOWNWARDS ) {
/* x += (height >> 1) - height; */
x -= (height + 1) >> 1;
} else {
x -= height >> 1;
}
break;
case GPT_YCENTREBASE: /* skew to bottom of char */
if( myflags & GPT_YDOWNWARDS ) {
x += ((baseline + 1) >> 1) - height;
} else {
x -= (baseline + 1) >> 1;
}
break;
case GPT_YTOP:
if( myflags & GPT_YDOWNWARDS ) {
x -= height;
}
break;
case GPT_YBASELINE:
default:
if( myflags & GPT_YDOWNWARDS ) {
x += baseline - height;
} else {
x -= baseline;
}
break;
} /* switch */
if( y < 0 ) {
rastlen += y;
y = 0;
}
lowi = rastlen - rp->BitMap->Rows;
if( lowi > 0 ) {
rastlen -= lowi;
} else {
lowi = 0;
}
maxbit = rastlen - 1;
if( myflags & GPT_YDOWNWARDS ) {
if( lowi ) {
maxbit -= lowi;
lowi = 0;
}
temp = x + height;
for( j = myrp.TxHeight - 1; j >= 0; --j ) {
if( GPT_XTHICKEN ) {
dest = temp - (j << 1) - 1;
} else {
dest = temp - j;
}
for( i = maxbit; i >= lowi; --i ) {
/* if no error and not background colour */
if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
WritePixel( rp, (long) dest, (long) y + i );
if( myflags & GPT_XTHICKEN ) {
WritePixel( rp, (long) dest + 1, (long) y + i );
}
}
} /* for */
} /* for */
} else { /* else upwards */
for( i = maxbit; i >= lowi; --i ) {
dest = y + maxbit - i;
for( j = myrp.TxHeight - 1; j >= 0; --j ) {
/* if no error and not background colour */
if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
if( myflags & GPT_XTHICKEN ) {
temp = j << 1;
WritePixel( rp, (long) x + temp + 1, (long) dest );
WritePixel( rp, (long) x + temp, (long) dest );
} else {
WritePixel( rp, (long) x + j, (long) dest );
}
}
} /* for */
} /* for */
}
getRidOfBitMap( myrp.BitMap );
} else {
switch( myflags & GPT_XFLAGS ) {
case GPT_XRIGHT:
x -= rastlen - 1;
break;
case GPT_XCENTRE:
x -= rastlen >> 1;
break;
case GPT_XLEFT:
default:
break;
} /* switch */
switch( myflags & GPT_YFLAGS ) { /* make y top of char */
case GPT_YBOTTOM:
y -= rp->TxHeight - 1;
break;
case GPT_YCENTRE:
y -= (rp->TxHeight - 1) >> 1; /* skew to top of char */
break;
case GPT_YCENTREBASE:
y -= (rp->TxBaseline + 1) >> 1; /* skew to bottom of char */
break;
case GPT_YTOP:
break;
case GPT_YBASELINE:
default:
y -= rp->TxBaseline;
break;
} /* switch */
y += rp->TxBaseline; /* adjust top to baseline for Text() */
/* note rp's TxBaseline is offset from top pixel of character */
Move( rp, (long) x, (long) y );
Text( rp, s, (long) len );
}
return( maxrastlen );
} /* positionText */
SHAR_EOF
cat << \SHAR_EOF > requester.c
/*
* FILE: requester.c
* Support routines for putting up an Auto Request or creating a Requester.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 31-Oct-88 Jan Sven Trabandt added more functionality to gimmeRequester
*/
#define I_AM_REQUESTER
#include <clib/macros.h>
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/requester.h"
#include "gimmelib/macros.h"
extern struct GfxBase *GfxBase;
SHORT gimmeAutoRequest( window, s, textattr )
struct Window *window;
UBYTE *s;
struct TextAttr *textattr;
{
struct IntuiText itext, ptext, ntext;
SHORT xsize, ysize, width;
if( !s ) {
s = (UBYTE *) GAR_DUMMY_TEXT;
}
itext.FrontPen = AUTOFRONTPEN;
itext.BackPen = AUTOBACKPEN;
itext.DrawMode = AUTODRAWMODE;
itext.LeftEdge = AUTOLEFTEDGE;
itext.TopEdge = AUTOTOPEDGE;
itext.ITextFont = textattr;
itext.IText = s;
itext.NextText = AUTONEXTTEXT;
ptext = itext; /* struct copy */
ntext = itext; /* struct copy */
ptext.IText = gimAutReqPostext;
ntext.IText = gimAutReqNegtext;
xsize = 0;
if( textattr ) {
ysize = textattr->ta_YSize;
} else if( window ) {
ysize = window->RPort->TxHeight;
xsize = window->RPort->TxWidth;
} else {
ysize = GfxBase->DefaultFont->tf_YSize;
}
if( !xsize ) {
xsize = GfxBase->DefaultFont->tf_XSize;
}
width = MAX(IntuiTextLength(&itext),
IntuiTextLength(&ptext) + IntuiTextLength(&ntext) + 3*xsize);
return (
AutoRequest( window, &itext, &ptext, &ntext, ENDGADGET, ENDGADGET,
(ULONG) width + xsize * GAR_BORDER_WIDTH,
(ULONG) ysize * GAR_HEIGHT )
);
} /* gimmeAutoRequest */
#define XLEEWAY 8 /* border space */
#define YLEEWAY 4
#define MIN_WIDTH 50 /* minimum dimensions if calculating dimension(s) */
#define MIN_HEIGHT 20 /* not counting y leeways */
struct Requester *gimmeRequester( mh, left, top, width, height, backfill,
gp, s, textattr, flags )
void **mh;
SHORT left, top;
SHORT width, height;
UBYTE backfill;
struct Gadget *gp;
UBYTE *s;
struct TextAttr *textattr;
ULONG flags;
{
register struct Requester *req;
register struct Border *bp;
struct Gadget *gadg;
SHORT len, extra;
void *mymh = NULL;
GUESS
QUIF( !mh );
req = chainAllocMem( &mymh, (ULONG)sizeof(struct Requester),
MEMF_PUBLIC | MEMF_CLEAR );
QUIF( !req );
if( flags & POINTREL ) {
req->RelLeft = left;
req->RelTop = top;
}
req->LeftEdge = left;
req->TopEdge = top;
req->ReqGadget = gp;
req->ReqText = gimmeIntuiText( &mymh, s != NULL ? s : (UBYTE *)"",
textattr, 0 );
QUIF( !req->ReqText );
req->ReqText->TopEdge = YLEEWAY;
req->ReqText->LeftEdge = XLEEWAY;
req->ReqText->BackPen = backfill;
req->Flags = flags;
req->BackFill = backfill;
if( width <= 0 ) {
width = IntuiTextLength( req->ReqText );
extra = 0;
for( gadg = gp; gadg; gadg = gadg->NextGadget ) {
if( gadg->Flags & GRELRIGHT ) {
len = -gadg->LeftEdge;
} else {
len = gadg->LeftEdge;
}
if( !(gadg->Flags & GRELWIDTH) ) {
len += gadg->Width;
}
if( len > width ) {
width = len;
} else if( gadg->Activation & (RIGHTBORDER | LEFTBORDER) ) {
if( len > extra ) {
extra = gadg->Width;
}
}
} /* for */
width += extra + XLEEWAY;
if( width <= 0 ) {
width = MIN_WIDTH;
}
}
req->Width = width;
if( height <= 0 ) {
if( textattr ) {
height = textattr->ta_YSize;
} else {
height = MIN_HEIGHT;
}
extra = 0;
for( gadg = gp; gadg; gadg = gadg->NextGadget ) {
if( gadg->Flags & GRELBOTTOM ) {
len = -gadg->TopEdge;
} else {
len = gadg->TopEdge;
}
if( !(gadg->Flags & GRELHEIGHT) ) {
len += gadg->Height;
}
if( len > height ) {
height = len;
} else if( gadg->Activation & (BOTTOMBORDER | TOPBORDER) ) {
if( len > extra ) {
extra = gadg->Height;
}
}
} /* for */
height += extra + YLEEWAY;
}
req->Height = height;
bp = gimmeBorder( &mymh, width - 4, height - 2 );
if( bp ) {
bp->LeftEdge = 2;
bp->TopEdge = 1;
bp->FrontPen = ~backfill;
req->ReqBorder = bp;
/* double thickness vertical lines */
bp = gimmeBorder( &mymh, width - 6, height - 2 );
if( bp ) {
bp->LeftEdge = 3;
bp->TopEdge = 1;
bp->FrontPen = ~backfill;
req->ReqBorder->NextBorder = bp;
}
}
linkChainMem( mh, mymh );
return( req );
ENDGUESS
if( mymh ) {
chainFreeMem( mymh );
}
return( NULL );
} /* gimmeRequester */
SHAR_EOF
cat << \SHAR_EOF > screen.c
/*
* FILE: screen.c
* Support for Intuition screen stuff.
*
* Public Domain, but keep our names in it as the original authors.
* 31-Aug-88 Jan Sven Trabandt first release version
* 30-Sep-88 Jan Sven Trabandt gimmeNewScreen checks width more closely
*/
#define I_AM_SCREEN
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/window.h"
#include "gimmelib/globals.h"
extern struct GfxBase *GfxBase;
struct NewScreen *gimmeNewScreen( modes, type, depth, title, textattr )
ULONG modes, type;
SHORT depth;
UBYTE *title;
struct TextAttr *textattr;
{
register struct NewScreen *ns;
#ifdef GIMME_WIMPY
if( depth < 1 || depth > 8 ) {
return( NULL );
}
#endif
ns = (struct NewScreen *) AllocMem( (ULONG)sizeof(struct NewScreen),
MEMF_PUBLIC | MEMF_CLEAR );
if( ns ) {
ns->Width = GfxBase->NormalDisplayColumns;
if( modes & HIRES ) {
if( ns->Width <= 350 ) {
ns->Width <<= 1;
}
} else {
if( ns->Width > 350 ) {
ns->Width >>= 1;
}
}
ns->Height = STDSCREENHEIGHT;
ns->Depth = depth;
ns->BlockPen = 1;
ns->ViewModes = modes;
ns->Type = type;
ns->Font = textattr;
ns->DefaultTitle = title;
}
return( ns );
} /* gimmeNewScreen */
short getRidOfNewScreen( ns )
struct NewScreen *ns;
{
#ifdef GIMME_WIMPY
if( !ns ) {
return( -1 );
}
#endif
FreeMem( ns, (ULONG)sizeof(struct NewScreen) );
return( 0 );
} /* getRidOfNewScreen */
struct Screen *gimmeScreen( ns, winptr, depth, IDCMPflags, winflags )
struct NewScreen *ns;
struct Window **winptr;
SHORT depth;
ULONG IDCMPflags, winflags;
{
struct Screen *screen;
struct NewWindow *nw;
struct NewScreen *myns;
if( !(myns = ns) ) {
ns = gimmeNewScreen( HIRES, CUSTOMSCREEN, depth, NULL, &gimMyFont );
}
if( ns ) {
screen = OpenScreen( ns );
if( screen && winptr ) {
nw = gimmeNewWindow( NULL, screen, 0, 1, IDCMPflags, winflags );
if( !nw ) {
*winptr = NULL;
} else {
*winptr = gimmeWindow( nw, 0, 0, 0 );
getRidOfNewWindow( nw );
if( !*winptr ) {
getRidOfScreen( screen, NULL );
screen = NULL;
} else {
ShowTitle( screen, FALSE ); /* hide screen title */
}
}
}
}
if( !myns && ns ) {
getRidOfNewScreen( ns );
}
return( screen );
} /* gimmeScreen */
struct Screen *gimmeScreenLazy( ns, winptr, depth )
struct NewScreen *ns;
struct Window **winptr;
SHORT depth;
{
return( gimmeScreen(ns, winptr, depth, IDCMP_DEFAULT, FLAGS_DEFAULT) );
} /* gimmeScreenLazy */
short getRidOfScreen( screen, window )
struct Screen *screen;
struct Window *window;
{
if( window ) {
getRidOfWindow( window );
}
if( screen ) {
CloseScreen( screen );
}
return( 0 );
} /* getRidOfScreen */
short lowerScreen( screen, toheight )
struct Screen *screen;
SHORT toheight;
{
register SHORT i;
#ifdef GIMME_WIMPY
if( !screen ) {
return( -1 );
}
#endif
for( i = screen->TopEdge | 1; i < toheight; i += 2 ) {
MoveScreen( screen, 0L, 2L );
} /* for */
return( 0 );
} /* lowerScreen */
short raiseScreen( screen, toheight )
struct Screen *screen;
SHORT toheight;
{
register SHORT i;
#ifdef GIMME_WIMPY
if( !screen ) {
return( -1 );
}
#endif
for( i = screen->TopEdge & (~1); i >= toheight; i -= 2 ) {
MoveScreen( screen, 0L, -2L );
} /* for */
return( 0 );
} /* raiseScreen */
SHAR_EOF
cat << \SHAR_EOF > scrollbar.c
/*
* FILE: scrollbar.c
* Support routines for making scroll-bar and -button gadgets.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 30-Sep-88 Jan Sven Trabandt keep up with changes to gadget.c
*/
#define I_AM_SCROLLBAR
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/scrollbar.h"
#include "gimmelib/macros.h"
struct Gadget *gimmeOneScroll( window, id, dirflags, myflags )
struct Window *window;
USHORT id;
ULONG dirflags, myflags;
{
register struct Gadget *gp;
void *gadgmh = NULL;
USHORT *data;
USHORT *imagedata;
GUESS
QUIF( !id );
gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
MEMF_CLEAR | MEMF_PUBLIC );
QUIF( !gp );
gp->GadgetType = BOOLGADGET;
gp->GadgetRender = (APTR) gimmeImage( &gadgmh, GOS_BITDEPTH,
GOS_BITWIDTH, GOS_BITHEIGHT );
QUIF( !gp->GadgetRender );
if( dirflags & FREEVERT ) {
gp->LeftEdge = -(GOS_BITWIDTH -1);
gp->Width = GOS_BITWIDTH;
gp->Height = GOS_BITHEIGHT;
if( myflags & GOS_TOP ) {
if( window ) {
gp->TopEdge = window->BorderTop - 1;
} else {
gp->TopEdge = GIM_DFLT_TBHEIGHT;
}
gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT;
imagedata = gimDataOneScrollUp;
} else {
gp->TopEdge = -GIM_SZHEIGHT - (GOS_BITHEIGHT -1);
gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT | GRELBOTTOM;
imagedata = gimDataOneScrollDown;
}
gp->Activation = RELVERIFY | RIGHTBORDER;
} else { /* otherwise we have FREEHORIZ */
gp->TopEdge = -(GOS_BITHEIGHT -1);
gp->Width = GOS_BITWIDTH;
gp->Height = GOS_BITHEIGHT;
if( myflags & GOS_LEFT ) {
gp->LeftEdge = 0;
gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM;
imagedata = gimDataOneScrollLeft;
} else {
gp->LeftEdge = -GIM_SZWIDTH - (GOS_BITWIDTH - 1);
gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM | GRELRIGHT;
imagedata = gimDataOneScrollRight;
}
gp->Activation = RELVERIFY | BOTTOMBORDER;
}
copyDataImage( imagedata, (struct Image *) gp->GadgetRender );
if( window ) {
if( window->Flags & GIMMEZEROZERO ) {
gp->GadgetType |= GZZGADGET;
}
}
gp->GadgetID = id;
gp->UserData = gadgmh;
return( gp );
ENDGUESS
if( gadgmh ) {
chainFreeMem( gadgmh );
return( NULL );
}
} /* gimmeOneScroll */
struct Gadget *gimmeScrollBar( window, id, propflags, myflags )
struct Window *window;
USHORT id;
ULONG propflags, myflags;
{
register struct Gadget *gp;
SHORT ones_size = 0;
SHORT left, top, width, height;
ULONG gadgflags, activation;
void *gadgmh = NULL;
GUESS
QUIF( !id );
if( propflags & FREEVERT ) {
propflags &= ~FREEHORIZ;
if( myflags & GSB_ONE_SCROLL ) {
ones_size = GOS_BITHEIGHT;
}
left = - (GOS_BITWIDTH -1);
top = ones_size;
if( !(myflags & GSB_NO_TITLEBAR) ) {
if( window ) {
top += window->BorderTop - 1;
} else {
top += GIM_DFLT_TBHEIGHT;
}
}
width = GOS_BITWIDTH;
height = -top - ones_size - GIM_SZHEIGHT;
gadgflags = GADGHCOMP | GADGIMAGE | GRELRIGHT | GRELHEIGHT;
activation = RELVERIFY | RIGHTBORDER;
} else { /* otherwise we have FREEHORIZ */
propflags &= ~FREEVERT;
if( myflags & GSB_ONE_SCROLL ) {
ones_size = GOS_BITWIDTH;
}
left = ones_size;
top = - (GOS_BITHEIGHT -1);
width = -GIM_SZWIDTH - (ones_size<<1);
height = GOS_BITHEIGHT;
gadgflags = GADGHCOMP | GADGIMAGE | GRELBOTTOM | GRELWIDTH;
activation = RELVERIFY | BOTTOMBORDER;
}
gp = gimmePropGadget( window, id, left, top, width, height, NULL,
NULL, activation, propflags );
QUIF( !gp );
gp->Flags = gadgflags;
if( window ) {
((struct PropInfo *)gp->SpecialInfo)->VertBody =
0x0FFFFL * window->Height / window->MaxHeight;
((struct PropInfo *)gp->SpecialInfo)->HorizBody =
0x0FFFFL * window->Width / window->MaxWidth;
}
linkChainMem( &gp->UserData, gadgmh );
return( gp );
ENDGUESS
if( gadgmh ) {
chainFreeMem( gadgmh );
return( NULL );
}
} /* gimmeScrollBar */
struct Gadget *gimmeFullScrollBar( window, id, propflags, myflags, id1, id2 )
struct Window *window;
USHORT id;
ULONG propflags, myflags;
USHORT id1, id2;
{
register struct Gadget *gp;
GUESS
QUIF( !id );
gp = gimmeScrollBar( window, id, propflags, myflags | GSB_ONE_SCROLL );
QUIF( !gp );
/* top or left one-scroll */
gp->NextGadget = gimmeOneScroll( window, id1, propflags,
GOS_TOP | GOS_LEFT );
QUIF( !gp->NextGadget );
/* bottom or right one-scroll */
gp->NextGadget->NextGadget = gimmeOneScroll( window, id2, propflags,
GOS_BOT | GOS_RIGHT );
QUIF( !gp->NextGadget->NextGadget );
return( gp );
ENDGUESS
if( gp ) {
getRidOfGadgets( gp );
}
return( NULL );
} /* gimmeFullScrollBar */
SHAR_EOF
cat << \SHAR_EOF > sound.c
/*
* FILE: sound.c
* Support routines for reading IFF/8SVX files.
*
* Public Domain, but keep our names in it as the original authors.
* 09-Dec-87 Rico Mariani original code (modified by JST)
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#define I_AM_SOUND
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/sound.h"
#include <stdio.h>
#define GET(iffile) getc( iffile )
#define getId getLong
#define getLen getLong
#define getByte GET
#define skip(len, file) fseek(file, (long)(len), 1)
#define getV8H(v8h, file) fread(v8h, sizeof(Voice8Header), 1, file)
/* requires an existent variable 'char *errmsg' and a label 'failure_return' */
#define fail_and_return(msg) {errmsg = msg; goto failure_return;}
/* forward declarations */
static LONG getLong();
static WORD getWord();
static char noMemMsg[] = "insufficient memory\n";
static char badFileMsg[] = "corrupt or incomplete file\n";
SOUND *gimmeSound( filename )
UBYTE *filename;
{
LONG len, id;
SOUND *snd = NULL;
BYTE *p;
void *mh = NULL;
FILE *file = NULL;
char *errmsg = " ";
SHORT i;
if( !(file = fopen(filename, "r")) ) {
fail_and_return( "unable to open iff sound file for read\n" );
}
if( getId(file) != ID_FORM ) {
fail_and_return( "not IFF format\n" );
}
getLen( file );
if( getId(file) != ID_8SVX ) {
fail_and_return( "not 8SVX format\n" );
}
for( ;; ) {
getChunk( &id, &len, file );
if( ferror(file) || feof(file) ) {
fail_and_return( badFileMsg );
}
switch( id ) {
case ID_VHDR:
snd = chainAllocMem( &mh, (ULONG)sizeof(SOUND),
MEMF_PUBLIC | MEMF_CLEAR );
if( !snd ) {
fail_and_return( noMemMsg );
}
getV8H( &snd->vh, file );
if( len & 1 ) {
GET(file);
}
break;
case ID_BODY:
if( !snd ) {
fail_and_return( "didn't find VHDR chunk\n" );
}
switch( snd->vh.sCompression ) {
case sCmpNone:
snd->bodylen = len;
snd->body = chainAllocMem( &mh, len, MEMF_CHIP );
if( !snd->body ) {
fail_and_return( noMemMsg );
}
memget( snd->body, len, file );
break;
case sCmpFibDelta:
snd->bodylen = len << 1;
snd->body = chainAllocMem( &mh, (ULONG) snd->bodylen,
MEMF_CHIP );
if( !snd->body ) {
fail_and_return( noMemMsg );
}
p = AllocMem( len, MEMF_PUBLIC );
if( !p ) {
fail_and_return( noMemMsg );
}
memget( p, len, file );
DUnpack( p, len, snd->body );
FreeMem( p, len );
break;
default:
fail_and_return( "unknown compression form\n" );
break;
} /* switch */
if( len & 1 ) {
GET(file);
}
if( ferror(file) ) {
fail_and_return( badFileMsg );
}
snd->memhead = mh;
fclose( file );
return( snd );
break;
case ID_NAME:
case ID_AUTH:
case ID_COPY:
case ID_ANNO:
case ID_ATAK:
case ID_RLSE:
default: /* unimplemented chunk type */
skip( EVEN(len), file );
break;
} /* switch */
} /* for */
failure_return: {}
if( Output() ) {
Write( Output(), errmsg, (ULONG)strlen(errmsg) );
}
if( mh ) {
chainFreeMem( mh );
}
if( file ) {
fclose( file );
}
return( NULL );
} /* gimmeSound */
short getRidOfSound( sound )
SOUND *sound;
{
#ifdef GIMME_WIMPY
if( !sound ) {
return( -1 );
}
#endif
chainFreeMem( sound->memhead );
return( 0 );
} /* getRidOfSound */
/* read an IFF Id */
static LONG getLong( file )
FILE *file;
{
register UBYTE p[4];
p[0] = GET(file);
p[1] = GET(file);
p[2] = GET(file);
p[3] = GET(file);
return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
} /* getLong */
/* read an IFF chunk header */
static getChunk( id, len, file )
LONG *id, *len;
FILE *file;
{
*id = getId( file );
*len = getLen( file );
} /* getChunk */
/* get len bytes from the file and put them into memory */
static memget( p, len, file )
UBYTE *p;
LONG len;
FILE *file;
{
for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
fread( p, (int) (len & 0x07fffL), 1, file );
} /* for */
} /* memget */
/* get a word */
static WORD getWord( file )
FILE *file;
{
WORD v;
v = GET(file) << 8;
return( v | GET(file) );
} /* getWord */
/* get the EGPoint info */
static getEGPoint( pnt, file )
EGPoint *pnt;
FILE *file;
{
pnt->duration = getWord( file );
pnt->dest = getLong( file );
} /* getEGPoint */
static BYTE codeToDelta[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
/* unpack a part of a fibonacci delta encoded sound sample */
static BYTE D1Unpack( source, n, dest, x )
BYTE *source;
LONG n;
BYTE *dest;
BYTE x;
{
UBYTE d;
LONG i, lim;
lim = n << 1;
for( i = 0; i < lim; ++i ) {
d = source[i>>1];
if( i & 1 ) {
d &= 0xf;
} else {
d >>= 4;
}
x += codeToDelta[d];
dest[i] = x;
} /* for */
return( x ); /* return last data value */
} /* D1Unpack */
/* unpack a fibonacci delta encoded sound sample */
static DUnpack( source, n, dest )
BYTE *source;
LONG n;
BYTE *dest;
{
D1Unpack( source + 2, n - 2, dest, source[1] );
} /* DUnpack */
SHAR_EOF
cat << \SHAR_EOF > stdstuff.c
/*
* FILE: stdstuff.c
* Support routines for creating and dealing with standard libraries
* and devices.
*
* Public Domain, but keep my name in it as the original author.
* 30-Sep-88 Jan Sven Trabandt added to gimme.lib
* 31-Oct-88 Jan Sven Trabandt added new options
* made getRidOfStdStuff more controllable
*/
#define I_AM_STDSTUFF
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/stdstuff.h"
#ifdef AZTEC_C
extern int Enable_Abort;
#endif AZTEC_C
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct DiskfontBase *DiskfontBase = NULL;
struct Device *TimerBase = NULL;
struct MsgPort *gimTimerPort = NULL;
struct timerequest *gimMasterTR = NULL;
struct timerequest *gimSlaveTR = NULL;
struct MsgPort *gimMainPort = NULL;
SHORT gimSubTasks = 0;
void *gimChainMem = NULL;
ULONG gimmeStdStuff( myflags, rev )
ULONG myflags;
SHORT rev;
{
if( myflags & GSS_DISABLEABORT ) {
#ifdef AZTEC_C
Enable_Abort = 0;
#endif
}
if( myflags & GSS_INTUITION ) {
if( !(IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", (long) rev)) ) {
return( GSS_INTUITION );
}
}
if( myflags & GSS_GFX ) {
if( !(GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", (long) rev)) ) {
return( GSS_GFX );
}
}
if( myflags & GSS_CLOSEWBENCH ) {
if( CloseWorkBench() ) {
return( GSS_CLOSEWBENCH );
}
}
if( myflags & GSS_DISKFONT ) {
if( !(DiskfontBase = (struct DiskfontBase *)
OpenLibrary("diskfont.library", (long) rev)) ) {
return( GSS_DISKFONT );
}
}
if( myflags & GSS_TIMER ) {
if( !(gimMasterTR = accessTimer(UNIT_MICROHZ, &gimTimerPort)) ) {
return( GSS_TIMER );
}
if( !(gimSlaveTR = gimmeTimeRequest(gimMasterTR)) ) {
return( GSS_TIMER );
}
}
if( myflags & GSS_SUBTASK ) {
if( initSubTasker(&gimSubTasks, &gimMainPort) ) {
return( GSS_SUBTASK );
}
}
return( 0L );
} /* gimmeStdStuff */
ULONG getRidOfStdStuff( myflags )
ULONG myflags;
{
if( myflags & GSS_MEMCHAIN ) {
if( gimChainMem ) {
chainFreeMem( gimChainMem );
gimChainMem = NULL;
}
}
if( myflags & GSS_SUBTASK ) {
if( gimMainPort ) {
handleSpecialSubTaskMsg( &gimSubTasks, &gimMainPort );
if( doneSubTasker(&gimSubTasks, &gimMainPort)
&& !(myflags & GSS_RUTHLESS) ) {
return( GSS_SUBTASK );
}
gimSubTasks = 0;
gimMainPort = NULL;
}
}
if( myflags & GSS_TIMER ) {
if( gimSlaveTR ) {
if( getRidOfTimeRequest(gimSlaveTR) && !(myflags & GSS_RUTHLESS) ) {
return( GSS_TIMER );
}
gimSlaveTR = NULL;
}
if( gimMasterTR ) {
if( releaseTimer(gimMasterTR, NULL) && !(myflags & GSS_RUTHLESS) ) {
return( GSS_TIMER );
}
gimMasterTR = NULL;
gimTimerPort = NULL;
}
}
if( myflags & GSS_DISKFONT ) {
if( DiskfontBase ) {
CloseLibrary( DiskfontBase );
DiskfontBase = NULL;
}
}
if( myflags & GSS_OPENWBENCH ) {
if( OpenWorkBench() && !(myflags & GSS_RUTHLESS) ) {
return( GSS_OPENWBENCH );
}
}
if( myflags & GSS_GFX ) {
if( GfxBase ) {
CloseLibrary( GfxBase );
GfxBase = NULL;
}
}
if( myflags & GSS_INTUITION ) {
if( IntuitionBase ) {
CloseLibrary( IntuitionBase );
IntuitionBase = NULL;
}
}
if( myflags & GSS_ENABLEABORT ) {
#ifdef AZTEC_C
Enable_Abort = 1;
#endif
}
return( 0L );
} /* getRidOfStdStuff */
SHAR_EOF
cat << \SHAR_EOF > subtask.c
/*
* FILE: subtask.c
* Support routines for spawning subtasks (not processes).
* This means the subtask shares the same memory space as its parent task.
*
* Note: this "library" is re-entrant, so any task can spawn and keep track
* of its own subtasks independantly of other users of this "library".
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 31-Oct-88 Jan Sven Trabandt (de)initialize routines moved to subtinit.c
* so that minimal routines need to be
* linked in when using stdstuff.c
* renamed getRidOfSubTask to killSubTask
*/
#define I_AM_SUBTASK
#include "gimmelib/gimmefuncs.h"
#define MIN_STACK 100L
#define MIN_COUNT 2
#define MAX_EXTRA 2
typedef struct {
struct Message msg;
ULONG flags;
APTR ptr;
} DONEMSG;
#define DONEFLAG ((1L << 31) + 1857329L)
/* internal use only!!
*
* NAME: a4get, a4put
*
* SYNOPSIS: a4value = a4get();
* a4put( a4value );
* LONG a4value;
*
* DESCRIPTION: Get or put a value into register A4. MANX specific!!!!
* These two functions are support routines for task creation.
* BECAUSE A4 GETS CLEARED IN THE SUBTASK
* and Manx needs it as a base pointer in small-code model.
* Manx's geta4() won't work if its code is too far away,
* so this ensures a4 is set up.
* I'm not sure if this is only in small code and/or small data.
*
static LONG a4get();
static VOID a4put();
#asm
cseg
_a4get:
move.l a4,d0
rts
_a4put:
move.l 4(a7),a4
rts
#endasm
struct Task *gimmeSubTask( countptr, portptr, stack_size, data_size,
myportptr )
SHORT *countptr;
struct MsgPort **portptr;
LONG stack_size, data_size;
struct MsgPort **myportptr;
{
struct Task *task;
DONEMSG *msg = NULL;
struct MemList *mymemlist;
struct myneeds {
struct MemList mn_head; /* 1 MemEntry in the head */
struct MemEntry mn_body[MIN_COUNT+MAX_EXTRA-1];
} myneeds;
UWORD count = 0;
myneeds.mn_head.ml_Node.ln_Type = NT_MEMORY;
myneeds.mn_head.ml_Node.ln_Pri = 0;
myneeds.mn_head.ml_Node.ln_Name = NULL;
if( data_size > 0L ) {
myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
myneeds.mn_head.ml_me[count].me_Length = data_size;
++count;
}
if( myportptr && portptr ) {
myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(DONEMSG);
++count;
}
/* leave stack and struct Task as last two memory blocks */
if( stack_size < MIN_STACK ) {
stack_size = MIN_STACK;
}
myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC;
myneeds.mn_head.ml_me[count].me_Length = stack_size;
++count;
myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(struct Task);
++count;
myneeds.mn_head.ml_NumEntries = count;
mymemlist = (struct MemList *) AllocEntry( &myneeds );
if( (ULONG)(mymemlist) & (1L<<31) ) {
return( NULL );
}
--count;
task = (struct Task *) mymemlist->ml_me[count].me_Addr;
NewList( &task->tc_MemEntry );
AddTail( &task->tc_MemEntry, mymemlist );
--count;
task->tc_SPLower = mymemlist->ml_me[count].me_Addr; /* stack */
task->tc_SPUpper = (APTR) (stack_size + (ULONG) task->tc_SPLower);
task->tc_SPReg = task->tc_SPUpper;
task->tc_Node.ln_Type = NT_TASK;
if( myportptr && portptr ) {
--count;
msg = (DONEMSG *) mymemlist->ml_me[count].me_Addr;
msg->msg.mn_Length = mymemlist->ml_me[count].me_Length;
msg->msg.mn_Node.ln_Type = NT_MESSAGE;
msg->ptr = (APTR) *portptr; /* save subtask monitoring port */
msg->flags = DONEFLAG;
} /* endif */
pushTaskStack( task, msg );
if( data_size > 0L ) {
--count;
task->tc_UserData = mymemlist->ml_me[count].me_Addr;
}
pushTaskStack( task, task->tc_UserData );
pushTaskStack( task, myportptr );
pushTaskStack( task, countptr );
return( task );
} /* gimmeSubTask */
/* internal use only!!
*
* pushTaskStack : push a long value onto the subtask's stack
* task struct and stack must already be initialized,
* task must not have been started yet.
static pushTaskStack( task, val )
struct Task *task;
LONG val;
{
--((LONG *)task->tc_SPReg);
*((LONG *)task->tc_SPReg) = val;
} /* pushTaskStack */
/* internal use only!!
*
* popTaskStack : pop a long value off the subtask's stack
* task struct and stack must already be initialized,
* task must not have been started yet.
static LONG popTaskStack( task )
struct Task *task;
{
return( *((LONG *)task->tc_SPReg)++ );
} /* popTaskStack */
VOID undoGimmeSubTask( task )
struct Task *task;
{
if( task ) {
FreeEntry( task->tc_MemEntry.lh_Head );
}
} /* undoGimmeSubTask */
VOID killSubTask( countptr, portptr, task )
SHORT *countptr;
struct MsgPort **portptr;
struct Task *task;
{
struct MsgPort *myport;
if( portptr && (myport = *portptr) ) {
*portptr = NULL;
DeletePort( myport );
}
/* It is permissible to do a Forbid() and RemTask(NULL) [kill myself]
* even though the following Permit() statement would not get executed
* since the OS will take care of things just fine.
*/
Forbid();
if( countptr ) {
--(*countptr);
}
RemTask( task );
Permit();
} /* killSubTask */
/* internal use only!!
*
* getRidOfMyself
* what's actually on the stack:
* func a4 countptr myport data msg -> see bridgeSubTask
* what getRidOfMyself thinks is there:
* ret-addr dum [countptr] [myport] [data] [msg]
* note it doesn't actually know about data, msg and port.
* thus countptr is 1 long past dum, etc.
static VOID getRidOfMyself( dum )
LONG dum;
{
LONG *parm;
DONEMSG *msg;
struct MsgPort *mp, *myport;
parm = &dum;
msg = (DONEMSG *) *(parm + 4);
if( msg && (myport = (struct MsgPort *) *(parm + 2)) ) {
mp = (struct MsgPort *) msg->ptr;
msg->ptr = (APTR) FindTask( NULL );
msg->msg.mn_ReplyPort = myport;
PutMsg( mp, msg );
for( ;; ) {
WaitPort( myport );
while ( msg = (DONEMSG *) GetMsg(myport) ) {
if( msg->msg.mn_Node.ln_Type != NT_REPLYMSG ) {
ReplyMsg( msg );
} else if( msg->flags == DONEFLAG ) {
goto gromyself_done;
}
} /* while */
} /* for */
}
gromyself_done:
killSubTask( *(parm + 1), parm + 2, NULL );
} /* getRidOfMyself */
/* internal use only!!
*
* bridgeSubTask
* Used as the actual initialPC for the subtask, it gets a message port
* if necessary and calls the real subtask routine.
* Also increments the subtask counter!!!!
* Also changes portptr on the stack to port (ie a pointer to a port, not
* a pointer to a pointer) so things are kosher for getRidOfMyself.
* startSubTask does the set-up so that the new subtask starts executing
* with this routine.
static VOID bridgeSubTask( func, a4, countptr, myportptr, data, msg )
long (*func)();
LONG a4;
SHORT *countptr;
struct MsgPort **myportptr;
APTR data;
DONEMSG *msg;
{
a4put( a4 );
if( countptr ) {
Forbid();
++(*countptr);
Permit();
}
if( myportptr ) {
*myportptr = CreatePort( NULL, 0L );
if( !*myportptr ) {
return;
}
*((struct MsgPort **)&myportptr) = *myportptr;
}
func( data );
} /* bridgeSubTask */
short startSubTask( task, name, pri, initialpc, finalpc )
struct Task *task;
char *name;
BYTE pri;
void (*initialpc)(), (*finalpc)();
{
if( !task || !initialpc ) {
return( -1 );
}
task->tc_Node.ln_Name = name;
task->tc_Node.ln_Pri = pri;
pushTaskStack( task, a4get() );
pushTaskStack( task, initialpc );
if( !finalpc ) {
(APTR) finalpc = (APTR) getRidOfMyself;
}
AddTask( task, bridgeSubTask, finalpc );
return( 0 );
} /* startSubTask */
SHAR_EOF
cat << \SHAR_EOF > subtinit.c
/*
* FILE: subtinit.c
* Support routines for spawning subtasks (not processes).
* This means the subtask shares the same memory space as its parent task.
*
* Note: this "library" is re-entrant, so any task can spawn and keep track
* of its own subtasks independantly of other users of this "library".
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt split from subtask.c
*/
#define I_AM_SUBTINIT
#include "gimmelib/gimmefuncs.h"
#define GIM_BUILTIN
#include "gimmelib/macros.h"
short initSubTasker( countptr, portptr )
SHORT *countptr;
struct MsgPort **portptr;
{
if( countptr ) {
*countptr = 0;
}
if( portptr ) {
*portptr = CreatePort( NULL, 0L );
if( !*portptr ) {
return( -1 );
}
}
return( 0 );
} /* initSubTasker */
short doneSubTasker( countptr, portptr )
SHORT *countptr;
struct MsgPort **portptr;
{
struct MsgPort *myport;
if( countptr && *countptr ) {
return( -1 );
}
if( portptr && (myport = *portptr) ) {
*portptr = NULL;
DeletePort( myport );
}
return( 0 );
} /* doneSubTasker */
/****************************************************************/
/* routines to handle printing messages from subtasks to Output()
extern struct Message *gimmeMessage();
struct print_msg {
struct Message msg;
ULONG flags;
UBYTE buf[164];
};
typedef struct print_msg PRINTMSG;
#define PRINTMSG_FLAG 218572L
short doPrintf( port, replyport, s, p1, p2, p3, p4 )
struct MsgPort *port, *replyport;
UBYTE *s;
LONG p1, p2;
double p3, p4;
{
PRINTMSG *pmsg;
if( !port || !s ) {
return( -1 );
}
pmsg = (PRINTMSG *) gimmeMessage( (ULONG)sizeof(PRINTMSG), replyport );
if( !pmsg ) {
return( -1 );
}
pmsg->flags = PRINTMSG_FLAG;
sprintf( pmsg->buf, s, p1, p2, p3, p4 );
PutMsg( port, pmsg );
if( replyport ) {
WaitPort( replyport );
pmsg = (PRINTMSG *) GetMsg( port );
/***
if( pmsg->msg.mn_Node.ln_Type != NT_REPLYMSG
|| pmsg->flags != PRINTMSG_FLAG ) {
}
***/
getRidOfMessage( pmsg );
} /* endif */
return( 0 );
} /* doPrintf */
SHORT handleSpecialSubTaskMsg( countptr, portptr )
SHORT *countptr;
struct MsgPort **portptr;
{
PRINTMSG *msg;
SHORT died = 0;
if( !portptr || !*portptr ) {
return( died );
}
while( msg = (PRINTMSG *) GetMsg(*portptr) ) {
if( msg->flags == PRINTMSG_FLAG ) {
if( Output() ) {
Forbid();
Write( Output(), msg->buf, (ULONG)strlen(msg->buf) );
Permit();
}
if( !msg->msg.mn_ReplyPort ) {
getRidOfMessage( msg );
} else {
ReplyMsg( msg );
}
} else { /* otherwise its a DONEMSG (see subtask.c) */
ReplyMsg( msg );
++died;
} /* endif */
} /* while */
return( died );
} /* handleSpecialSubTaskMsg */
SHAR_EOF
cat << \SHAR_EOF > timer.c
/*
* FILE: timer.c
* Support routines for dealing with the timer device.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 31-Oct-88 Jan Sven Trabandt most routines moved to timerstuff.c
* so that minimal routines need to be
* linked in when using stdstuff.c
*/
#define I_AM_TIMER
#include "gimmelib/gimmefuncs.h"
extern struct Device *TimerBase;
struct timerequest *accessTimer( unit, portptr )
ULONG unit;
struct MsgPort **portptr;
{
struct MsgPort *timerport = NULL;
struct timerequest *tr;
#ifdef GIMME_WIMPY
if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
return( NULL );
}
#endif
if( portptr && *portptr ) {
timerport = *portptr;
} else {
timerport = CreatePort( NULL, 0L );
if( portptr ) {
*portptr = timerport;
}
}
if( !timerport ) {
return( NULL );
}
tr = CreateExtIO( timerport, (ULONG)sizeof(struct timerequest) );
if( !tr ) {
DeletePort( timerport );
} else {
if( OpenDevice(TIMERNAME, unit, tr, 0L) ) {
DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
DeletePort( timerport );
return( NULL );
}
}
TimerBase = tr->tr_node.io_Device;
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
return( tr );
} /* accessTimer */
LONG releaseTimer( tr, saveport )
register struct timerequest *tr;
struct MsgPort *saveport;
{
struct MsgPort *tport;
LONG err;
#ifdef GIMME_WIMPY
if( !tr ) {
return( 0L );
}
#endif
tport = tr->tr_node.io_Message.mn_ReplyPort;
if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
if( err = AbortIO(tr) ) {
return( err );
}
Remove( tr );
}
CloseDevice( tr );
DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
if( !saveport && tport ) {
DeletePort( tport );
}
return( 0L );
} /* releaseTimer */
struct timerequest *gimmeTimeRequest( trmaster )
struct timerequest *trmaster;
{
register struct timerequest *tr;
#ifdef GIMME_WIMPY
if( !trmaster ) {
return( NULL );
}
#endif
tr = CreateExtIO( trmaster->tr_node.io_Message.mn_ReplyPort,
(ULONG)sizeof(struct timerequest) );
if( tr ) {
tr->tr_node.io_Device = trmaster->tr_node.io_Device;
tr->tr_node.io_Unit = trmaster->tr_node.io_Unit;
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
}
return( tr );
} /* gimmeTimeRequest */
LONG getRidOfTimeRequest( tr )
register struct timerequest *tr;
{
LONG err;
#ifdef GIMME_WIMPY
if( !tr ) {
return( 0L );
}
#endif
Forbid();
tr->tr_node.io_Message.mn_ReplyPort = NULL;
if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
if( err = AbortIO(tr) ) {
Permit();
return( err );
}
Remove( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
}
Permit();
DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
return( 0L );
} /* getRidOfTimeRequest */
SHAR_EOF
cat << \SHAR_EOF > timerstuff.c
/*
* FILE: timerstuff.c
* Support routines for dealing with timerequests and additional timer support.
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt split from timer.c
*/
#define I_AM_TIMERSTUFF
#include "gimmelib/gimmefuncs.h"
extern struct Device *TimerBase;
LONG timeDelay( secs, micros, unit, mytr )
ULONG secs, micros;
ULONG unit;
struct timerequest *mytr;
{
register struct timerequest *tr;
LONG err;
if( !secs && !micros ) {
return( 0L ); /* so we don't crash, return right away */
}
if( mytr ) {
tr = mytr;
} else {
#ifdef GIMME_WIMPY
if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
return( -1L );
}
#endif
if( !secs ) {
unit = UNIT_MICROHZ; /* force more efficient method */
}
if( !(tr = accessTimer(unit, NULL)) ) {
return( -1L );
}
}
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = secs;
tr->tr_time.tv_micro = micros;
err = DoIO( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
if( !mytr ) {
releaseTimer( tr, NULL );
}
return( err );
} /* timeDelay */
struct timerequest *timeDelayAsync( secs, micros, unit, tr )
ULONG secs, micros;
ULONG unit;
register struct timerequest *tr;
{
if( !tr ) {
#ifdef GIMME_WIMPY
if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
return( NULL );
}
#endif
if( !secs ) {
unit = UNIT_MICROHZ; /* force more efficient method */
}
if( !(tr = accessTimer(unit, NULL)) ) {
return( NULL );
}
}
if( !secs && !micros ) {
micros = 1L; /* so we don't crash on zero-delay */
}
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = secs;
tr->tr_time.tv_micro = micros;
SendIO( tr );
return( tr );
} /* timeDelayAsync */
LONG waitTimer( tr )
struct timerequest *tr;
{
LONG err = 0L;
#ifdef GIMME_WIMPY
if( !tr ) {
return( err );
}
#endif
err = WaitIO( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
return( err );
} /* waitTimer */
LONG killTimeDelay( tr )
register struct timerequest *tr;
{
LONG err;
#ifdef GIMME_WIMPY
if( !tr ) {
return( 0L );
}
#endif
Forbid();
if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
if( err = AbortIO(tr) ) {
Permit();
return( err );
}
Remove( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
}
Permit();
return( 0L );
} /* killTimeDelay */
short getSysTime( secs, micros, mytr )
ULONG *secs, *micros;
struct timerequest *mytr;
{
register struct timerequest *tr;
if( mytr ) {
tr = mytr;
} else {
if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) {
return( -1 );
}
}
tr->tr_node.io_Command = TR_GETSYSTIME;
DoIO( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
if( secs ) {
*secs = tr->tr_time.tv_secs;
}
if( micros ) {
*micros = tr->tr_time.tv_micro;
}
if( !mytr ) {
releaseTimer( tr, NULL );
}
return( 0 );
} /* getSysTime */
short setSysTime( secs, micros, mytr )
ULONG secs, micros;
struct timerequest *mytr;
{
register struct timerequest *tr;
if( mytr ) {
tr = mytr;
} else {
if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) {
return( -1 );
}
}
tr->tr_node.io_Command = TR_SETSYSTIME;
tr->tr_time.tv_secs = secs;
tr->tr_time.tv_micro = micros;
DoIO( tr );
tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
if( !mytr ) {
releaseTimer( tr, NULL );
}
return( 0 );
} /* setSysTime */
SHAR_EOF
cat << \SHAR_EOF > window.c
/*
* FILE: window.c
* Support routines for dynamic (de)allocation of (new)windows.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#define I_AM_WINDOW
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/window.h"
#include <graphics/gfxbase.h>
extern struct GfxBase *GfxBase;
struct NewWindow *gimmeNewWindow( title, screen, leftedge, topedge,
IDCMPflags, flags )
UBYTE *title;
struct Screen *screen;
SHORT leftedge, topedge;
ULONG IDCMPflags, flags;
{
register struct NewWindow *nw;
nw = (struct NewWindow *) AllocMem( (ULONG)sizeof(struct NewWindow),
MEMF_PUBLIC | MEMF_CLEAR );
if( !nw ) {
return( NULL );
}
nw->DetailPen = GNW_DETAIL_PEN;
nw->BlockPen = GNW_BLOCK_PEN;
nw->IDCMPFlags= IDCMPflags;
nw->Flags = flags;
nw->Title = title;
nw->MinWidth = GNW_MIN_WIDTH;
nw->MinHeight = GNW_MIN_HEIGHT;
nw->LeftEdge = leftedge;
nw->TopEdge = topedge;
if( screen ) {
nw->Type = CUSTOMSCREEN;
nw->Screen = screen;
nw->MaxWidth = screen->Width;
nw->MaxHeight = screen->Height;
} else {
nw->Type = WBENCHSCREEN;
nw->MaxWidth = GfxBase->NormalDisplayColumns;
nw->MaxHeight = GfxBase->NormalDisplayRows;
}
nw->Width = nw->MaxWidth - nw->LeftEdge;
nw->Height = nw->MaxHeight - nw->TopEdge;
return( nw );
} /* gimmeNewWindow */
short getRidOfNewWindow( nw )
struct NewWindow *nw;
{
#ifdef GIMME_WIMPY
if( !nw ) {
return( -1 );
}
#endif
FreeMem( nw, (ULONG)sizeof(struct NewWindow) );
return( 0 );
} /* getRidOfNewWindow */
struct Window *gimmeWindow( nw, depth, width, height )
struct NewWindow *nw;
SHORT depth, width, height;
{
struct Window *window;
struct NewWindow *mynw;
if( !(mynw = nw) ) {
nw = gimmeNewWindow( NULL, NULL, 0, 1, IDCMP_DEFAULT, FLAGS_DEFAULT );
}
for( ;; ) { /* dummy loop with break at end */
if( nw ) {
if( nw->Flags & SUPER_BITMAP ) {
if( !(nw->BitMap = gimmeBitMap(depth, width, height)) ) {
break;
}
}
window = OpenWindow( nw );
if( !window ) {
if( nw->Flags & SUPER_BITMAP ) {
getRidOfBitMap( nw->BitMap );
}
} else {
window->UserData = (BYTE *) nw->BitMap;
}
}
break;
} /* for */
if( !mynw && nw ) {
getRidOfNewWindow( nw );
}
return( window );
} /* gimmeWindow */
short getRidOfWindow( window )
struct Window *window;
{
struct BitMap *bm = NULL;
struct IntuiMessage *imsg;
#ifdef GIMME_WIMPY
if( !window ) {
return( -1 );
}
#endif
if( window->Flags & SUPER_BITMAP ) {
bm = (struct BitMap *) window->UserData;
}
if( window->MenuStrip ) {
ClearMenuStrip( window );
}
while( imsg = (struct IntuiMessage *) GetMsg(window->UserPort) ) {
ReplyMsg( imsg );
} /* while */
CloseWindow( window );
if( bm ) {
getRidOfBitMap( bm );
}
} /* getRidOfWindow */
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.